"""
This script is used to run all the test of openttd performance
"""
import os,time, NetworkCommunication, string
from threading import Timer
from Performance import Performance
from Configuration import Configuration
import math, DescriptionParser, FaultTolerance,socket, RunTimeManager, thread
ft = True
Configuration = Configuration()
instanceOfPrun = 10
totalPrunLimit = 1
experiments = []
servers = [
#           "fs0",
#           ,
#           "fs1.das3.liacs.nl",
#           "fs2.das3.science.uva.nl",
           "fs3.das4.tudelft.nl"
#           , "fs4.das3.science.uva.nl"
           ]


def isStillSomeExpInWaiting(servername, expName, factor, hostname="fs3"):
    cmd =  "qstat |grep sshen";
    print hostname
    if servername != hostname:
        cmd = "ssh -i "+ Configuration.sshKey + " sshen@"+ servername + " '" + cmd + "'";
    print cmd
    file = os.popen(cmd)
    lines = file.readlines()
    foundWaiting = False
    totalRun = 0
    if len(lines) == 0:
        print "len(lines)==0 return False"
        return False
    for line in lines:
        tup = string.split(line)
        print tup
        if tup[4] !="r":
            print "foundWaiting"
            return True
        if tup[4] == "r":
            print "totalRun =", totalRun +1
            totalRun = totalRun + 1
    if foundWaiting == True:
        return True
    if totalRun >= totalPrunLimit :
        return True

    print "There is still machine to run on ", servername
    return False;

def getDelay(delay):
    if delay >0 :
        return "-delay %d "%delay
    else: return ""

def runExpInServer(servername, expId, expName, maxYear, factor, instances=16,delay = 0, permachine=1):
    print "-------------------------------------------------"
    ttt = Configuration.getTimelimit(maxYear, servername)
    ddd = getDelay(delay)
    numberOfProcess = "-%d "%permachine
    cmd = "prun -v -np %d "%instances + ddd + numberOfProcess + ttt + "python /home/sshen/OpenTTDTestingDas3/src/JobExecution.py " + "%d"%expId + " " + expName + " " + "%d"%maxYear + " " + "%d"%factor
    
#    servername = findServer(expName, factor)
    if ft == True:
        cmd = cmd + " nullPath ft"
    hostname = Configuration.getHostName()
    if hostname != servername:
        print "ssh -i "+ Configuration.sshKey + " sshen@"+ servername + " '" + cmd + "'& "
        cmd = "ssh -i "+ Configuration.sshKey + " sshen@"+ servername + " '" + cmd + "'"
    
    os.system(cmd + "&")
    print "-----------------------------------------------------"
    return True

def runInMyComputer(expId, expName, maxYear, factor):
    print "-------------------------------------------------"
    servername = "root@130.161.159.13"
    filename = "../openttd.cfg"
    cmd = "scp -i "+ Configuration.sshKey + " " + filename + " " + servername + ":~/.openttd/"
    os.system(cmd)
    filename = "../game_start.scr"
    cmd = "scp -i "+ Configuration.sshKey + " " + filename + " " + servername + ":~/1.0.5_modified/bin/scripts/"
    os.system(cmd)
    
    cmd = "cd ~/OpenTTDTestingDas3/src; python JobExecution.py " + "%d"%expId + " " + expName + " " + "%d"%maxYear + " " + "%d"%factor + " /home/siqi/"
    
    if ft == True:
        cmd = cmd + " " + "ft"
    os.system("ssh -i "+ Configuration.sshKey + " " + servername + " '" + cmd + "'&")
#    os.system(cmd + "&")
    print "-----------------------------------------------------"
    return True



def removeAutoSaveOnServer(servername):
    return
#    print "ssh -i "+ Configuration.sshKey + " sshen@"+servername + " 'rm -fr /home/sshen/.openttd/save/autosave' "
#    os.system("ssh -i "+ Configuration.sshKey + " sshen@"+servername + " 'rm -fr /home/sshen/.openttd/save/autosave'");

def copyAndDelResultFromDas3(servername):
#    print "scp -i "+ Configuration.sshKey + " " + " -r sshen@" + servername + ":/var/scratch/sshen/test_result .."
#    os.system("scp -i "+ Configuration.sshKey + " " + "-r sshen@" + servername + ":/var/scratch/sshen/test_result/* ../test_result/")
#    print "remove /var/scrach/sshen/test_result *"
#    os.system("ssh -i "+ Configuration.sshKey + " sshen@"+servername + " 'rm -fr /var/scratch/sshen/test_result/*'")

#    cmd = "scp -i "+ Configuration.sshKey + " -r /var/scratch/sshen/test_result/ siqi@130.161.159.13:~/das3_test_result/"
#    print cmd
#    os.system(cmd)
#    cmd = "rm -fr /var/scratch/sshen/test_result/*"
#    os.system(cmd)
#    print cmd
    return True

def copyfile(expName, servername, hostname):
#    filename = "../openttd.cfg"
#    print "scp -i "+ Configuration.sshKey + " " +  filename + " sshen@" + servername + ":/home/sshen/run/ "
#    os.system("scp -i "+ Configuration.sshKey + " " + filename + " sshen@" + servername + ":/home/sshen/run/ ")
#    filename = "../game_start.scr"
#    print "scp -i "+ Configuration.sshKey + " " + filename + " sshen@" + servername + ":/home/sshen/run/scripts/game_start.scr"
#    os.system("scp -i "+ Configuration.sshKey + " " + filename + " sshen@" + servername + ":/home/sshen/run/scripts/game_start.scr")
    
    filename = "../openttd.cfg"
#    print "scp -i "+ Configuration.sshKey + " " +  filename + " sshen@" + servername + ":/home/sshen/run/ "
    cmd = "cp " + filename + " /home/sshen/run/"
    if hostname != servername:
        cmd = "scp -i "+ Configuration.sshKey + " " +  filename + " sshen@" + servername + ":/home/sshen/run/ "
    os.system(cmd)
    filename = "../game_start.scr"
    cmd = "cp " + filename + " /home/sshen/run/scripts/game_start.scr"
    if hostname != servername:
        cmd = "scp -i "+ Configuration.sshKey + " " + filename + " sshen@" + servername + ":/home/sshen/run/scripts/game_start.scr"
#    print "scp -i "+ Configuration.sshKey + " " + filename + " sshen@" + servername + ":/home/sshen/run/scripts/game_start.scr"
    os.system(cmd)

def changeConfigurationAndSendtoServer(servername, expName, factor):
    hostname = Configuration.getHostName()
    Configuration.initExp(expName)
    Configuration.expVarChange(expName, factor)
    server = servername
    copyfile(expName, server, hostname)
    time.sleep(2)
    copyAndDelResultFromDas3(server)
    removeAutoSaveOnServer(server)
    return True

#expNames = ["1a1-1024", "1a1-2048", "1a4", "1a1-64", "1a1-128", "1a1-256"]
#expNames = ["1a11_0_0", "1a11_0_1", "1a11_0_2", "1a11_0_3", "1a11_1_1", "1a11_2_1", "1a11_3_1", "1a11_1_2"]
expNames = ["1a1"]

def insertExpIntoExperiments():
    global experiments
    for expName in expNames:
        l1 = DescriptionParser.getFactors(expName)
        l = [expName]
        l.append("anyServer")
        l.extend(l1)
        experiments.append(l)
    
def listenNewJobs():
    global experiments
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    s.bind(("",RunTimeManager.port))
    s.listen(50)
    while(True):
        con,addr = s.accept();
        con.settimeout(10)
        str = con.recv(1024)
        con.send("ok")
        print "receive new exps " + str
        l = list(string.split(str))
        experiments.append(l)
#        if len(list) == 1:
#            con.send("server")
#            serveraddress = str
        con.close()
    s.close()
    return True

def fakeTestAll():
    global experiments
    insertExpIntoExperiments()
    thread.start_new_thread(listenNewJobs, ())
    while True:
        print "sleeping"
        if len(experiments) ==0:
            time.sleep(10)
        else:
            exp = experiments.pop()
            expName = exp[0]
            servername = exp[1:2]
            factors = exp[2:]
            for factor in factors:
                print expName, factor, "run in ", servername
                time.sleep(1)
        time.sleep(1)

def getServer(expName, factor):
    hostname = Configuration.getHostName()
    while True:
        for servername in servers:
            if isStillSomeExpInWaiting(servername, expName, factor, hostname) == False:
                print servername, "is Idle"
                return servername
        time.sleep(10)

def realRunExpriment(expId, expName, i, servername, maxYear):
    print "start experiment on ", expId, expName, "factor", i, servername, "maxYear", maxYear
    changeConfigurationAndSendtoServer(servername, expName, i)
#            numberOfMachine = min(16,i)
#            if numberOfMachine < 16:
#                numberOfMachine = numberOfMachine + 1;
    numberOfMachine = i;
    if expName[0:1] == "2":
        NetworkCommunication.start_server(numberOfMachine+1, i)            
        delay = 2
        runExpInServer(servername, expId, expName, maxYear, i, 1, delay) #openttdserver
        tt = numberOfMachine//8
        runExpInServer(servername, expId, expName, maxYear, i, tt, delay, 8)
    
        if numberOfMachine%8 !=0:
            time.sleep(delay * numberOfMachine + delay)
            runExpInServer(servername, expId, expName, maxYear, i, 1, delay, numberOfMachine%8)
        time.sleep(300 * maxYear)
        NetworkCommunication.s.close()
        NetworkCommunication.enableRunFlag = False
    elif expName.find("4a")>=0:
        runInMyComputer(expId, expName, maxYear, i)
        time.sleep(5)
        runExpInServer(servername, expId, expName, maxYear, i, i, 2)
        time.sleep(300 * maxYear)
    elif expName.find("5a")>=0:
        NetworkCommunication.start_server(numberOfMachine+1, i)            
        delay = 2
        runExpInServer(servername, expId, expName, maxYear, i, 1, delay) #openttdserver
        numberOfMachine = numberOfMachine -1
        tt = numberOfMachine//8
        runExpInServer(servername, expId, expName, maxYear, i, tt, delay, 8)
    
        if numberOfMachine%8 !=0:
            time.sleep(delay * numberOfMachine + delay)
            runExpInServer(servername, expId, expName, maxYear, i, 1, delay, numberOfMachine%8)
        runInMyComputer(expId, expName, maxYear)
        time.sleep(300 * maxYear)
        NetworkCommunication.s.close()
        NetworkCommunication.enableRunFlag = False  
    elif expName.find("1a") >=0:
        print "the max year is ", maxYear
        runExpInServer(servername, expId, expName, maxYear, i, instanceOfPrun, 0)
        time.sleep(100 * maxYear)
#        num = FaultTolerance.getErrorNum(expName, i, instanceOfPrun)
#                import sys
#                sys.stdin.read()
        if ft == True:
            rep = 5
            while(rep > 0):
                print "begin fault tolerance " + time.asctime()
                while isStillSomeExpInWaiting(servername, expName, i, Configuration.getHostName()) == True:
                    time.sleep(30)
                num = FaultTolerance.getErrorNum(expName, i, instanceOfPrun)
                print "expect number of experiment result %d" %instanceOfPrun
                print "incorrect is %d"%num
                if num > 0:
                    expId = Configuration.increaseId()
                    print "begin fault tolerance run " + time.asctime()
                    runExpInServer(servername, expId, expName, maxYear, i, num, 0)
                elif num == 0:
                    break
                rep = rep - 1
def testAll():
    global expNames
    print expNames
    thread.start_new_thread(listenNewJobs, ())
    for expName in expNames:
#        for expName in expNames:
#        while len(expNames) == 0:
#            time.sleep(5)
#        if len(expNames) > 0:
#            expName = expNames.pop()
#        if len(expNames) == 0 :
#            break;
#        expName = expNames.pop()
        Configuration.increaseId()
        expId = Configuration.getId();    
        maxYear = Configuration.getMaxYear(expName)
        print DescriptionParser.getFactors(expName)
        for i in DescriptionParser.getFactors(expName):
            servername = getServer(expName, i)
            print "found a server " + servername
            thread.start_new_thread(realRunExpriment,(expId, expName, i, servername, maxYear))
            time.sleep(30)
if __name__ == "__main__":
    fakeTestAll()
